package lectores;

import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.sql.Statement;
import lectores.parsersXLSX.ProcesadorXLSX;
import lectores.parsersXLSX.XLSXHandler;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.xml.sax.SAXException;

public class LectorConveniosPrimaPagada extends LectorConvenios {
    
    private File archivoExcel;
    private Workbook libroConveniosPrimaPagada;
    private int mesSeleccionado;
    private int tipoFiltroPeriodo;
    private final int[] INDICES_DATOS_VALIDOS = {0, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 22, 36, 37};
    private String queryCampos = "INSERT INTO convenios_pp(PERIODO, ID_AGENTE, SISTEMA_ORIGEN, NOMBRE_AGENTE, ID_RAMO_CONTABLE,"
            + " NOM_RAMO, ID_SUBR_CONTABLE, NOM_SUBRAMO, ID_SUB_RAMO_ORIGEN, ID_PROMOTORIA, NOM_PROMOTORIA, PRIMA_PAGADA,"
            + " MARCA,  SINIES_TOTAL, RAMO, COLUMNA) ";
    private Statement st;
    private boolean metioRegistroMes = false;
        
    public LectorConveniosPrimaPagada(File archivoExcel, int mesSeleccionado, int tipoFiltroPeriodo, Statement st)
            throws InvalidFormatException, FileNotFoundException, IOException, SQLException, SAXException, OpenXML4JException, ParserConfigurationException, ExcelMalFormadoException {
        this.archivoExcel = archivoExcel;
        this.mesSeleccionado = mesSeleccionado;
        this.tipoFiltroPeriodo = tipoFiltroPeriodo;
        this.st = st;
        creaMapeoDañosVida();
        creaMapeoColumnas();
        cargaArchivo();
    }
    
    void cargaArchivo() throws InvalidFormatException, FileNotFoundException, IOException, SQLException, SAXException, OpenXML4JException, ParserConfigurationException, ExcelMalFormadoException {
        creaTablaConvenios();
        
        if(archivoExcel.getPath().endsWith(".xlsx")) {
            OPCPackage paqueteExcel = OPCPackage.open(archivoExcel.getPath(), PackageAccess.READ);
            ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(paqueteExcel);
            XSSFReader xssfReader = new XSSFReader(paqueteExcel);
            StylesTable styles = xssfReader.getStylesTable();
            XLSXHandler manejadorContenido = new XLSXHandler(styles, strings, this, mesSeleccionado, tipoFiltroPeriodo);
            ProcesadorXLSX procesadorXLSX = new ProcesadorXLSX(manejadorContenido, xssfReader);
            procesadorXLSX.process();
        } else {
            InputStream inp = new FileInputStream(archivoExcel);
            libroConveniosPrimaPagada = WorkbookFactory.create(inp);
            llenaTablaConveniosXLS();
        }
        
        if(!metioRegistroMes) {
            throw new ExcelMalFormadoException(ExcelMalFormadoException.MES_NO_ENCONTRADO, archivoExcel);
        }
    }
        
    private void creaTablaConvenios() throws SQLException {
        String sql = null;
        st.executeUpdate("DROP TABLE IF EXISTS convenios_pp");
        sql = "CREATE TABLE convenios_pp (PERIODO INTEGER, ID_AGENTE INTEGER, SISTEMA_ORIGEN VARCHAR(500),"
            + " NOMBRE_AGENTE VARCHAR(500), ID_RAMO_CONTABLE INTEGER, NOM_RAMO VARCHAR(500), ID_SUBR_CONTABLE INTEGER,"
            + " NOM_SUBRAMO VARCHAR(500), ID_SUB_RAMO_ORIGEN INTEGER, ID_PROMOTORIA INTEGER, NOM_PROMOTORIA VARCHAR(500),"
            + " PRIMA_PAGADA DOUBLE, MARCA INTEGER,  SINIES_TOTAL DOUBLE, RAMO INTEGER, COLUMNA INTEGER)";
        st.executeUpdate(sql);
    }

    public void insertaRegistro(String datos, int renglon) throws SQLException, ExcelMalFormadoException {
        datos = datos.replace("'", "&").replace(",", "&").replace("&", "").trim();
        String[] renglonParseado = preparaRenglon(datos);
        if(renglonParseado != null) {
            validaCampos(renglonParseado, renglon);
            String queryValores = construyeSQLValores(renglonParseado, renglon, tipoFiltroPeriodo, mesSeleccionado, archivoExcel);
            if(queryValores != null) {
                st.execute(queryCampos + queryValores);
                metioRegistroMes = true;
            }
        }
    }
  
    private void llenaTablaConveniosXLS() throws ExcelMalFormadoException, SQLException {
        Sheet hojaConvenios = libroConveniosPrimaPagada.getSheetAt(0);
        
        Row renglonActual = null;
        for(int j = 1; j < hojaConvenios.getLastRowNum(); j++) {
            renglonActual = hojaConvenios.getRow(j);
            
            if(renglonActual == null) {
                throw new ExcelMalFormadoException(j, 0, ExcelMalFormadoException.RENGLON_VACIO, archivoExcel);
            }
            
            String[] valores = preparaRenglon(construyeRenglon(renglonActual));
            if(valores.length != 14) {
                throw new ExcelMalFormadoException(ExcelMalFormadoException.FALTA_COLUMNA, archivoExcel);
            }
            
            String queryValores =  construyeSQLValores(valores, j, tipoFiltroPeriodo, mesSeleccionado, archivoExcel);
            if(queryValores != null) {
                st.executeUpdate(queryCampos + queryValores);
            }
        }
    }
    
    private String construyeRenglon(Row renglon) {      
        String linea = "";
        Cell celdaActual;
        
        for(int i = 0; i < renglon.getLastCellNum(); i++) {
            celdaActual = renglon.getCell(i);
            
            String campoActual = "";
            if(celdaActual == null) {
                linea = linea + "|";
                continue;
            }
            
            boolean eraNumero = true;
            
            if(celdaActual.getCellType() == Cell.CELL_TYPE_STRING) {
                campoActual = celdaActual.getStringCellValue();
                campoActual = campoActual.replace("'", " ").replace(",", " ").replace(" ", "").trim();
                try {
                    Double.parseDouble(campoActual);
                } catch (NumberFormatException nfe) {
                    eraNumero = false;
                }
            
                if(eraNumero) {
                    campoActual = "" + Double.parseDouble(campoActual);
                }
            }
            
            if(celdaActual.getCellType() == Cell.CELL_TYPE_NUMERIC &&
                    (i == 2 || i == 7 || i == 9 || i == 11)) {
                campoActual = "" + (int) celdaActual.getNumericCellValue();
            } else if(celdaActual.getCellType() == Cell.CELL_TYPE_NUMERIC) {
                campoActual = "" + celdaActual.getNumericCellValue();
            }
            
            campoActual = campoActual.replace("'", " ").replace(",", " ").replace(" ", "").trim();
            
            if(i == renglon.getLastCellNum() - 1) {
                linea = linea + campoActual;
            } else {
                linea = linea + campoActual + "|";
            }
        }
        
        return linea;
    }
    
    public String[] preparaRenglon(String renglon) {
        String[] datosRenglon = new String[INDICES_DATOS_VALIDOS.length];
        String[] datosParseados = renglon.split("\\|");
        
        for(int i = 0; i < INDICES_DATOS_VALIDOS.length; i++) {
            String datoActual = datosParseados[INDICES_DATOS_VALIDOS[i]];
            
            if(INDICES_DATOS_VALIDOS[i] == 36) {
                if(datoActual.equals("")) {
                    datoActual = "0";
                } else if(datoActual.trim().equals("X")) {
                    datoActual = "1";
                } else if(datoActual.trim().equals("DXP")) {
                    return null;
                }
            }
            
            datosRenglon[i] = datoActual;
        }
        
        return datosRenglon;
    }
    
    public void validaCampos(String[] campos, int renglon) throws ExcelMalFormadoException {
        
        //Valida el periodo
        if(campos[0].equals("P_INV")) {
            if(esFilaVacia(campos)) {
                campos[0] = "0000-00";
                return;
            } else {
                throw new ExcelMalFormadoException(renglon-1, 0, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
            }
        }
        
        //Valida id_agente
        try {
            Integer.parseInt(campos[1]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 2, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        } 
        if(Integer.parseInt(campos[1]) == -1) {
            throw new ExcelMalFormadoException(renglon-1, 2, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
        
        //Valida id_ramo_subcontable
        int id_ramo_subc = 0;
        try {
            id_ramo_subc = Integer.parseInt(campos[4]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 7, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
        if(!(id_ramo_subc >= 1 && id_ramo_subc <= 36)) {
            throw new ExcelMalFormadoException(renglon-1, 7, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
        
        //Valida id_promotoria
        try {
            Integer.parseInt(campos[9]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 12, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
        if(Integer.parseInt(campos[9]) == -1) {
            throw new ExcelMalFormadoException(renglon-1, 12, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
        
        //Valida primapagada
        try {
            Double.parseDouble(campos[11]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 22, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
                
        //Valida siniestros
        try {
            Double.parseDouble(campos[13]);
        } catch(Exception ex) {
            throw new ExcelMalFormadoException(renglon-1, 37, ExcelMalFormadoException.DATO_INESPERADO, archivoExcel);
        }
    }
    
    private boolean esFilaVacia(String[] campos) {
        boolean filavacia = true;

        for(int i = 1; i < campos.length; i++) {
            if(i == 1 || i == 9) {
                filavacia &= (campos[i].equals("-1") || campos[i].equals("0"));
            } else {
                filavacia &= campos[i].equals("0");
            }
        }
        
        return filavacia;
    }
    
    public String construyeSQLValores(String[] valores, int renglon, int tipoFiltroPeriodo, int mesSeleccionado, File archivoExcel) throws ExcelMalFormadoException {
        String queryValores = " VALUES (";
        int mes = -1;
        try {
            mes =  Integer.parseInt(valores[0].substring(valores[0].length() - 2));
            valores[0] = "" + mes;
        } catch (NumberFormatException nfe) {
            throw new ExcelMalFormadoException(renglon, 0, ExcelMalFormadoException.TIPO_INESPERADO, archivoExcel);
        }
        
        switch(tipoFiltroPeriodo) {
            case FILTRO_BONOS_PRODUCCION:
                if(mesSeleccionado % 3 == 0) {
                    if(!(mesSeleccionado - 2 <= mes && mes <= mesSeleccionado)) {
                        return null;
                    }
                }
                break;
            case FILTRO_BONOS_CALIDAD:
                if(mesSeleccionado < mes) {
                    return null;
                }
                break;
        }

        for(int k = 0; k < valores.length; k++) {
            
            boolean esDouble = true;
            if(valores[k].equals("-")) 
                valores[k] = "" + 0.0;
            
            try {
                Double.parseDouble(valores[k]);
            } catch(NumberFormatException nfe) {
                esDouble = false;
            }
                
            if(esDouble && (INDICES_DATOS_VALIDOS[k] == 22 || INDICES_DATOS_VALIDOS[k] == 36)) {
                queryValores += valores[k] + ",";
            } else {
                boolean esNumero = true;
                try {
                    if(valores[k].length() != 0) {
                        Integer.parseInt("" + (valores[k].charAt(0)));
                    } else {
                        queryValores += "0,";
                        continue;
                    }
                } catch(NumberFormatException nfe) {
                    esNumero = false || (valores[k].charAt(0) == '+' || valores[k].charAt(0) == '-');
                }
                
                try {
                    Integer.parseInt("" + (valores[k].charAt(valores[k].length() - 1)));
                } catch(NumberFormatException nfe) {
                    esNumero = false;
                }
                
                if(esNumero) {
                    queryValores += valores[k].replace(" ", "") + ",";
                } else {
                    queryValores += "'" + valores[k] + "'" + ",";
                }
            }
        }
            
        int ramo = clasificaRamo(valores[2], valores[4], archivoExcel);
        int columna = columnaCorresp(valores[2], valores[4]);
        queryValores += ramo +", "+columna+ ")";
        return queryValores;
    }
    
}
